package com.electromagnetic.industry.software.manage.service.serviceimpl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.StrFormatter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.electromagnetic.industry.software.common.enums.EffectFlagEnum;
import com.electromagnetic.industry.software.manage.mapper.RolePermissionMapper;
import com.electromagnetic.industry.software.manage.pojo.models.EdFileInfo;
import com.electromagnetic.industry.software.manage.pojo.models.RolePermission;
import com.electromagnetic.industry.software.manage.pojo.req.PublishedFileDTO;
import com.electromagnetic.industry.software.manage.service.RolePermissionService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper, RolePermission> implements RolePermissionService {

    @Resource
    private RolePermissionMapper rolePermissionMapper;

    /**
     * 同步新权限
     *
     * @param currentPermission
     * @param infoId
     */
    @Transactional
    @Override
    public void syncNewPermissions(List<RolePermission> currentPermission, String infoId) {

        Assert.notNull(currentPermission, StrFormatter.format("权限参数无效"));

        LambdaQueryWrapper<RolePermission> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RolePermission::getFileId, infoId)
                .eq(RolePermission::getEffectFlag, EffectFlagEnum.EFFECT.code);
        List<RolePermission> oldPermissions = this.list(queryWrapper);

        Set<String> newPermissionSet = currentPermission.stream()
                .map(p -> p.getRoleId() + "_" + p.getPermissionCode())
                .collect(Collectors.toSet());

        List<RolePermission> permissionsToDisable = oldPermissions.stream()
                .filter(p -> !newPermissionSet.contains(p.getRoleId() + "_" + p.getPermissionCode()))
                .toList();

        log.info("失效旧权限: {}", permissionsToDisable);

        // 删除不需要的权限
        disableOldPermissions(permissionsToDisable);

        // 批量插入/更新新权限
        insertOrUpdateNewPermissions(currentPermission);
    }

    /**
     * 批量失效旧权限
     */
    @Override
    public void disableOldPermissions(List<RolePermission> oldPermissions) {
        if (!oldPermissions.isEmpty()) {
            List<String> idsToDisable = oldPermissions.stream()
                    .map(RolePermission::getId)
                    .toList();
            this.update(new LambdaUpdateWrapper<RolePermission>()
                    .set(RolePermission::getEffectFlag, EffectFlagEnum.NOT_EFFECTIVE.code)
                    .in(RolePermission::getId, idsToDisable));
        }
    }

    /**
     * 插入或激活新权限（使用 ON DUPLICATE KEY UPDATE 机制）
     */
    @Override
    @Transactional
    public void insertOrUpdateNewPermissions(List<RolePermission> newPermission) {
        if (!newPermission.isEmpty()) {
            for (RolePermission rp : newPermission) {
                rp.setEffectFlag(EffectFlagEnum.EFFECT.code);
                // 查询包括已失效的记录
                RolePermission exist = this.getOne(new LambdaQueryWrapper<RolePermission>()
                        .eq(RolePermission::getFileId, rp.getFileId())
                        .eq(RolePermission::getRoleId, rp.getRoleId())
                        .eq(RolePermission::getPermissionCode, rp.getPermissionCode()));
                if (exist != null) {
                    rp.setId(exist.getId()); // 赋值已有 ID，避免重复插入
                    rp.setEffectFlag(EffectFlagEnum.EFFECT.code); //重新激活记录
                }
            }
            this.saveOrUpdateBatch(newPermission);
        }
    }

    /**
     * 获取新权限
     *
     * @param publishedFileDTO
     * @return
     */
    @Override
    public List<RolePermission> getCurrentPermission(PublishedFileDTO publishedFileDTO) {
        return rolePermissionMapper.getCurrentPermission(publishedFileDTO);
    }

    /**
     * 在树形结构变动后同步权限
     *
     * @param prjId
     */
    @Transactional
    @Override
    public void syncPermissionsAfterTreeUpdate(List<EdFileInfo> files, String prjId) {

        log.info("开始同步项目权限：{}", prjId);

        // 对files分层
        TreeMap<Integer, List<EdFileInfo>> levelMap = new TreeMap<>();
        for (EdFileInfo file : files) {
            int len = file.getFilePath().split("_").length;
            levelMap.computeIfAbsent(len, k -> new ArrayList<>()).add(file);
        }

        // 获取叶子节点
        int maxLen = levelMap.lastKey();

        // 从最底层的叶子节点的上级节点开始遍历,更新权限
        for (int i = maxLen - 1; i > 0; i--) {
            for (EdFileInfo fileInfo : levelMap.get(i)) {
                String infoId = fileInfo.getId();
                if (isLeafNode(infoId, files)) {
                    continue;
                }
                PublishedFileDTO publishedFileDTO = new PublishedFileDTO();
                publishedFileDTO.newInit();
                publishedFileDTO.setFileId(infoId);
                List<RolePermission> currentPermission = getCurrentPermission(publishedFileDTO);
                syncNewPermissions(currentPermission, infoId);
            }
        }
        log.info("同步项目权限结束：{}", prjId);
    }

    private boolean isLeafNode(String id, List<EdFileInfo> files) {
        Set<String> parentIdSet = files.stream()
                .map(EdFileInfo::getParentId)
                .collect(Collectors.toSet());
        return !parentIdSet.contains(id);
    }

    /**
     * 逻辑删除
     *
     * @param roleId
     * @param fileId
     * @return
     */

    @Transactional
    @Override
    public boolean logicRemove(String roleId, String fileId) {
        // 参数校验
        if (roleId == null && fileId == null) {
            throw new IllegalArgumentException("必须提供至少一个参数");
        }
        // 执行逻辑删除
        return this.update(
                new LambdaUpdateWrapper<RolePermission>()
                        .set(RolePermission::getEffectFlag, EffectFlagEnum.NOT_EFFECTIVE.code)
                        .eq(fileId != null, RolePermission::getFileId, fileId)
                        .eq(roleId != null, RolePermission::getRoleId, roleId)
                        .eq(RolePermission::getEffectFlag, EffectFlagEnum.EFFECT.code)
        );
    }
}
